/*
 * Copyright (C) 2008  Ben Motmans  <ben.motmans@gmail.com>
 * Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdarg.h>
#include <stdbool.h>

#include <libgalaxium.h>
#include <gst/gst.h>

void destroy_bin (playInfo *info);
static gboolean bus_callback (GstBus *bus, GstMessage *msg, gpointer user_data);

void libgalaxium_gstreamer_init ()
{
	/* init GStreamer */
	gst_init (NULL, NULL);
}

void libgalaxium_gstreamer_set_eos_callback (playInfo* info, ManagedEosCallback callback)
{
	info->eosCallback = callback;
}

void libgalaxium_gstreamer_set_error_callback (playInfo* info, ManagedErrorCallback callback)
{
	info->errorCallback = callback;
}

playInfo* libgalaxium_gstreamer_open (char* filename)
{
	GstElement *playbin;
	GstBus *bus;

	/* set up */
	playbin = gst_element_factory_make ("playbin", "play");

	if (playbin == NULL)
		return NULL;

	playInfo* info = g_new0 (playInfo, 1);
	info->playbin = playbin;

	bus = gst_pipeline_get_bus (GST_PIPELINE (playbin));
	gst_bus_add_watch (bus, bus_callback, info);
	gst_object_unref (bus);

	g_object_set (G_OBJECT (playbin), "uri", filename, NULL);

	return info;
}

void libgalaxium_gstreamer_close (playInfo *info)
{
	destroy_bin (info);

	free (info);
}

void libgalaxium_gstreamer_play (playInfo* info)
{
	if (info != NULL && info->playbin != NULL)
		gst_element_set_state (info->playbin, GST_STATE_PLAYING);
}

void libgalaxium_gstreamer_stop (playInfo* info)
{
	if (info != NULL && info->playbin != NULL)
		gst_element_set_state (info->playbin, GST_STATE_PAUSED);
}

void destroy_bin (playInfo *info)
{
	if (info->playbin != NULL)
	{
		gst_element_set_state (GST_ELEMENT (info->playbin), GST_STATE_NULL);
		gst_object_unref (GST_OBJECT (info->playbin));
		info->playbin = NULL;
	}
}

gboolean bus_callback (GstBus *bus, GstMessage *msg, gpointer user_data)
{
	playInfo *info = (playInfo *)user_data;

	if (info == NULL)
		return FALSE;
	
	switch (GST_MESSAGE_TYPE (msg))
	{
		case GST_MESSAGE_EOS:
		{
			if (info->eosCallback != NULL)
				info->eosCallback (info);
			
			break;
		}
		case GST_MESSAGE_ERROR: /* display the error */
		{
			gchar *debug;
			GError *err;

			destroy_bin (info);
			
			gst_message_parse_error (msg, &err, &debug);
			
			if (info->errorCallback != NULL)
				info->errorCallback (info, err->domain, err->code, err->message, debug);
			
			g_free (debug);
			g_error_free (err);
	
			break;
		}
		default: break;
	}
	
	return TRUE;
}

